// #pragma once
#include <iostream>
#include <queue>
#include <mutex>
#include <thread>
#include <condition_variable>
using namespace std;


#define NUM 5

template<class T>
class threadPool
{
private:
	bool isEmpty()
	{
		return _taskQueue.size()==0;
	}
	void lockQueue()
	{
		pthread_mutex_lock(&_mutex);
	}
	void unlockQueue()
	{
		pthread_mutex_unlock(&_mutex);
	}
	void wait()
	{
		pthread_cond_wait(&_cond,&_mutex);
	}
	void wakeup()
	{
		pthread_cond_signal(&_cond);
	}
public:
	threadPool(int num = NUM)
		:_threadNum(NUM)
	{
		pthread_mutex_init(&_mutex,nullptr);
		pthread_cond_init(_cond,nullptr);
	}
	~threadPool()
	{
		pthread_mutex_destory(&_mutex);
		pthread_cond_destroy(&_cond);
	}
	//线程池中线程的执行例程
	void* routine(void* arg)
	{
		pthread_detach(pthread_self());
		threadPool* self= (threadPool*)arg;
		while(true)
		{
			self->lockQueue();
			while(self->isEmpty()) self->wait();
			T task;
			self->pop(task);
			self->unlockQueue();
			//处理任务，可以解锁了-高效体现之处
			task.run();
		}
	}
	void threadPoolInit()
	{
		pthread_t tid;
		for(int i=0;i<_threadNum;i++)
		{
			pthread_create(&tid,nullptr,routine,this);
		}
	}
	//往任务队列中放任务--主线程调用
	void push(const T& task)
	{
		lockQueue();
		_taskQueue.push(task);
		unlockQueue();
		wakeup();
	}
	void pop(const T& task)
	{
		task = _taskQueue.front();
		_taskQueue.pop();
	}
private:
	std::queue<T> _taskQueue;
	int _threadNum;
	pthread_mutex_t _mutex;
	pthread_cond_t _cond;
};

template <class T>
class BlockQueue
{
public:
	BlockQueue(int size = 20)
		: maxsize(size)
	{}

	void push(const T& val)
	{
		unique_lock<mutex> lock(mtx);

		product.wait(lock, [&]() { return q.size() < maxsize; });

		q.push(val);
		cout << "生产者生产了: " << val << endl;
		consume.notify_all();
	}

	T pop()
	{
		unique_lock<mutex> lock(mtx);

		consume.wait(lock, [&]() { return !q.empty(); });

		T res = q.front();
		q.pop();
		cout << "消费者消费了: " << res << endl;
		product.notify_all();

		return res;
	}

private:
	mutex mtx;
	condition_variable product;
	condition_variable consume;
	queue<T> q;
	int maxsize;
};

void product(BlockQueue<int>* q)
{
	int i = 0;
	while (1)
	{
		q->push(i++);
		//this_thread::sleep_for(chrono::seconds(1));
	}
}

void consume(BlockQueue<int>* q)
{
	while (1)
	{
		q->pop();
		this_thread::sleep_for(chrono::seconds(1));
	}
}

int main()
{
	BlockQueue<int> q;
	thread t1(consume, &q);
	thread t2(product, &q);

	t1.join();
	t2.join();
	return 0;
}

// typedef void *(*fun_t)(void *);//线程要执行的函数是参数和返回值都为void*
// class ThreadData
// {
// public:
//     void *args_;//线程拥有的数据
//     std::string name_;//线程的名字
// };
// class Thread
// {
// public:
//     Thread(int num, fun_t callback, void *args) : func_(callback)
//     {
//         char nameBuffer[64];
//         snprintf(nameBuffer, sizeof nameBuffer, "Thread-%d", num);
//         name_ = nameBuffer;
//         tdata_.args_ = args;
//         tdata_.name_ = name_;
//     }
//     void start()
//     {
//         pthread_create(&tid_, nullptr, func_, (void*)&tdata_);//将线程名和参数都传给线程函数
//     }
//     void join()
//     {
//         pthread_join(tid_, nullptr);
//     }
//     std::string name()
//     {
//         return name_;
//     }
//     ~Thread()
//     {}
// private:
//     std::string name_;//线程名字
//     fun_t func_;//线程要执行的函数
//     ThreadData tdata_;//线程的名字和数据
//     pthread_t tid_;//线程ID
// };
// class Mutex
// {
// public:
//     Mutex(pthread_mutex_t *mtx):pmtx_(mtx)
//     {}
//     void lock() 
//     {
//         // std::cout << "要进行加锁" << std::endl;
//         pthread_mutex_lock(pmtx_);
//     }
//     void unlock()
//     {
//         // std::cout << "要进行解锁" << std::endl;
//         pthread_mutex_unlock(pmtx_);
//     }
//     ~Mutex()
//     {}
// private:
//     pthread_mutex_t *pmtx_;
// };
// // RAII风格的加锁方式
// class lockGuard
// {
// public:
//     lockGuard(pthread_mutex_t *mtx):mtx_(mtx)
//     {
//         mtx_.lock();
//     }
//     ~lockGuard()
//     {
//         mtx_.unlock();
//     }
// private:
//     Mutex mtx_;
// };

// #include<iostream>
// #include<pthread.h>
// #include<mutex>
// #include<queue>
// #include<functional>
// using namespace std;
// pthread_mutex_t MTX = PTHREAD_MUTEX_INITIALIZER;//用于初始化单例模式中要使用的锁
// typedef function<void(int)> func_t;
// void myprintf(int x)//模拟线程要执行的函数
// {
//     cout<<x<<" "<<endl;
// }
// class Task   //模拟线程要执行的任务
// {
// public:
//     Task(func_t func = myprintf):_func(func)
//     {}
// public:
//     func_t _func;
// };
// class ThreadPool
// {
// public:
//     static ThreadPool* GetInstance()
//     {
//         if(_singleton == nullptr)
//         {
//             pthread_mutex_lock(&MTX);
//             if(_singleton == nullptr)
//             {
//                 _singleton = new ThreadPool();
//                 _singleton->InitThreadPool();
//             }
//             pthread_mutex_unlock(&MTX);
//         }
//         return _singleton;
//     }
//     void InitThreadPool()//启动线程池
//     {
//         for(int i=0;i<_num;i++)
//         {
//             pthread_t tid;
//             if(pthread_create(&tid,nullptr,Routine,this)!=0)
//                 cout<<"线程启动失败"<<endl;
//         }
//         cout<<"线程池启动成功"<<endl;
//     }
//     static void* Routine(void* args)
//     {
//         ThreadPool* td = (ThreadPool*)args;
//         while(1)
//         {
//             //拿到任务区执行
//             Task t;
//             pthread_mutex_lock(&td->_mtx);//加锁
//             while(td->TaskQueueIsEmpty())//若资源不就绪就等待
//                 pthread_cond_wait(&td->_cond,&td->_mtx);
//             cout<<"开始执行任务"<<endl;
//             td->Pop(t);//任务队列的任务减一
//             pthread_mutex_unlock(&td->_mtx);
//             t._func(10);
//             cout<<"一次任务执行完毕"<<endl;
//         }
//     }
//     void Push(Task t)
//     {
//         pthread_mutex_lock(&_mtx);
//         _q.push(t);
//         pthread_mutex_unlock(&_mtx);
//         pthread_cond_signal(&_cond);
//         cout<<"任务push成功"<<endl;
//     }
//     void Pop(Task& t)
//     {
//         t = _q.front();
//         _q.pop();
//     }
//     bool TaskQueueIsEmpty()
//     {
//         return _q.size()==0?true:false;
//     }
// private:
//     ThreadPool(int num = 10):_num(num)
//     {
//         pthread_mutex_init(&_mtx,nullptr);
//         pthread_cond_init(&_cond,nullptr);
//     }
//     ThreadPool(const ThreadPool& td) = delete;
// public:
//     static ThreadPool* _singleton;
//     queue<Task> _q;
//     int _num;//创建线程的数量
//     pthread_mutex_t _mtx;
//     pthread_cond_t _cond;
// };
// ThreadPool* ThreadPool::_singleton = nullptr;

